package org.tuoren.official.service.impl;

import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.esotericsoftware.minlog.Log;
import com.idrsolutions.image.png.PngCompressor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.tuoren.common.core.exception.ServiceException;
import org.tuoren.common.core.utils.MapstructUtils;
import org.tuoren.common.core.utils.StringUtils;
import org.tuoren.common.core.utils.file.MimeTypeUtils;
import org.tuoren.common.oss.core.OssClient;
import org.tuoren.common.oss.entity.UploadResult;
import org.tuoren.common.oss.enumd.AccessPolicyType;
import org.tuoren.common.oss.factory.OssFactory;
import org.tuoren.official.service.IOssService;
import org.tuoren.official.util.ThumbnailUtil;
import org.tuoren.system.domain.SysOss;
import org.tuoren.system.domain.vo.SysOssVo;
import org.tuoren.system.mapper.SysOssMapper;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * 文件上传 服务层实现
 *
 * @author Lion Li
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class OssServiceImpl implements IOssService {

    private final SysOssMapper ossMapper;

    /**
     * 上传 MultipartFile 到对象存储服务，并保存文件信息到数据库
     *
     * @param file 要上传的 MultipartFile 对象
     * @return 上传成功后的 SysOssVo 对象，包含文件信息
     * @throws ServiceException 如果上传过程中发生异常，则抛出 ServiceException 异常
     */
    @Override
    public SysOssVo upload(String configKey, MultipartFile file) {
        log.info("开始上传---------");
        String originalfileName = file.getOriginalFilename();
        log.info("文件名称{}---------", originalfileName);
        String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
        log.info("suffix{}---------", suffix);
        OssClient storage = OssFactory.instance(configKey);
        log.info("storage{}---------", storage);
        String md5;
        UploadResult uploadResult;
        try {
            md5 = DigestUtil.md5Hex(file.getInputStream());
            if (StringUtils.equalsAnyIgnoreCase(suffix.substring(1), MimeTypeUtils.IMAGE_EXTENSION)) {
                /*file = ThumbnailUtil.of(file)
                    .identifyCompress(ThumbnailUtil.ratios[0])
                    .outputFormat(ThumbnailUtil.orgForm).asMultipartFiles()[0];*/
                //Thumbnails.of(file.getInputStream()).imageType(BufferedImage.TYPE_INT_ARGB).outputFormat("png").scale(1f).outputQuality(0.8f).toFile(new File(originalfileName));
            }
            uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
            log.info("uploadResult{}---------", uploadResult);
        } catch (IOException e) {
            throw new ServiceException(e.getMessage());
        }
        // 保存文件信息
        log.info("保存文件信息---------");
        return buildResultEntity(originalfileName, suffix, configKey, uploadResult, md5);
    }

    @Override
    public Boolean deleteWithValidByIds(Long ossId) {
        SysOss sysOss = ossMapper.selectById(ossId);
        OssClient storage = OssFactory.instance(sysOss.getService());
        storage.delete(sysOss.getUrl());
        return ossMapper.deleteById(ossId) > 0;
    }

    @Override
    public String getImageUrl(String ossid) {
        if (ossid == null) return "";
        SysOss sysOss = ossMapper.selectById(ossid);
        return sysOss == null ? "" : sysOss.getFileName();
    }

    @Override
    @NotNull
    public SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, UploadResult uploadResult, String md5) {
        SysOss oss = new SysOss();
        oss.setUrl(uploadResult.getUrl());
        oss.setFileSuffix(suffix);
        oss.setFileName(uploadResult.getFilename());
        oss.setOriginalName(originalfileName);
        oss.setService(configKey);
        oss.setMd5(md5);
        log.info("保存文件信息{}---------", JSONUtil.toJsonStr(oss));
        ossMapper.insert(oss);
        log.info("保存成功---------");
        SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class);
        return this.matchingUrl(sysOssVo);
    }

    /**
     * 桶类型为 private 的URL 修改为临时URL时长为120s
     *
     * @param oss OSS对象
     * @return oss 匹配Url的OSS对象
     */
    private SysOssVo matchingUrl(SysOssVo oss) {
        log.info("matchingUrl---------");
        OssClient storage = OssFactory.instance(oss.getService());
        log.info("storage{}---------",storage);
        // 仅修改桶类型为 private 的URL，临时URL时长为120s
        if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) {
            log.info("PRIVATE---------");
            oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120));
        }
        log.info("PRIVATE22---------");
        return oss;
    }
}
